using System;
using System.Drawing;
using System.ComponentModel;

namespace WebChart
{
	public class ScatterChart : Chart
	{
		// Fields
		private DateRenderModeOption dateRenderMode;
		private DateRenderModeOption internalDateRenderMode;
		private ScatterLinesOption scatterLines;
		private XValueDataType xdataType;

		// Methods
		public ScatterChart()
		{
			this.internalDateRenderMode = DateRenderModeOption.Automatic;
			this.dateRenderMode = DateRenderModeOption.Automatic;
			this.xdataType = XValueDataType.Float;
			this.scatterLines = ScatterLinesOption.Lines;
		}

		public ScatterChart(ChartPointCollection data) : base(data)
		{
			this.internalDateRenderMode = DateRenderModeOption.Automatic;
			this.dateRenderMode = DateRenderModeOption.Automatic;
			this.xdataType = XValueDataType.Float;
			this.scatterLines = ScatterLinesOption.Lines;
		}

		public ScatterChart(ChartPointCollection data, Color color) : base(data, color)
		{
			this.internalDateRenderMode = DateRenderModeOption.Automatic;
			this.dateRenderMode = DateRenderModeOption.Automatic;
			this.xdataType = XValueDataType.Float;
			this.scatterLines = ScatterLinesOption.Lines;
		}

		private int GetMaxValue(DateRenderModeOption option, TimeSpan diff)
		{
			switch (option)
			{
				case DateRenderModeOption.Years:
					return (int) (diff.TotalDays / 365.25);

				case DateRenderModeOption.Months:
					return (int) (diff.TotalDays / 30.4375);

				case DateRenderModeOption.Weeks:
					return (int) (diff.TotalDays / 7);

				case DateRenderModeOption.Days:
					return (int) diff.TotalDays;

				case DateRenderModeOption.Hours:
					return (int) diff.TotalHours;
			}
			return (int) diff.TotalMinutes;
		}

		public override void GetMinMaxXValue(out int min, out int max)
		{
			ChartPointCollection data = base.Data;
			if ((data == null) || (data.Count == 0))
			{
				min = 0;
				max = 0;
			}
			else if (this.xdataType == XValueDataType.DateTime)
			{
				DateTime maxValue = DateTime.MaxValue;
				DateTime minValue = DateTime.MinValue;
				try
				{
					foreach (ChartPoint point in base.Data)
					{
						if (point.xvalue == null)
						{
							continue;
						}
						DateTime time3 = DateTime.Parse(point.xvalue);
						if (time3 > minValue)
						{
							minValue = time3;
						}
						if (time3 < maxValue)
						{
							maxValue = time3;
						}
					}
				}
				catch (FormatException)
				{
				}
				if (maxValue < base.Engine.scatterMinDateTime)
				{
					base.Engine.scatterMinDateTime = maxValue;
				}
				else
				{
					maxValue = base.Engine.scatterMinDateTime;
				}
				if (minValue > base.Engine.scatterMaxDateTime)
				{
					base.Engine.scatterMaxDateTime = minValue;
				}
				else
				{
					minValue = base.Engine.scatterMaxDateTime;
				}
				TimeSpan diff = minValue.Subtract(maxValue);
				if (this.dateRenderMode == DateRenderModeOption.Automatic)
				{
					if (diff.TotalDays > 1460)
					{
						this.internalDateRenderMode = DateRenderModeOption.Years;
					}
					else if (diff.TotalDays > 180)
					{
						this.internalDateRenderMode = DateRenderModeOption.Months;
					}
					else if (diff.TotalDays > 50)
					{
						this.internalDateRenderMode = DateRenderModeOption.Weeks;
					}
					else if (diff.TotalDays >= 4)
					{
						this.internalDateRenderMode = DateRenderModeOption.Days;
					}
					else if (diff.TotalHours > 2)
					{
						this.internalDateRenderMode = DateRenderModeOption.Hours;
					}
					else
					{
						this.internalDateRenderMode = DateRenderModeOption.Minutes;
					}
				}
				else
				{
					this.internalDateRenderMode = this.dateRenderMode;
				}
				max = this.GetMaxValue(this.internalDateRenderMode, diff) + 1;
				min = 0;
			}
			else
			{
				min = 0x7fffffff;
				max = -2147483648;
				float num = float.MaxValue;
				float num2 = float.MinValue;
				foreach (ChartPoint point2 in base.Data)
				{
					float xValueForData = (int) this.GetXValueForData(point2.xvalue);
					if (xValueForData > num2)
					{
						num2 = xValueForData;
					}
					if (xValueForData < num)
					{
						num = xValueForData;
					}
				}
				min = (int) num;
				max = (int) num2;
				if (num < base.Engine.scatterMinNumber)
				{
					base.Engine.scatterMinNumber = (float) min;
				}
				max -= (int) base.Engine.scatterMinNumber;
			}
		}

		public virtual float GetXValueForData(string data)
		{
			float num = 0f;
			try
			{
				try
				{
					if (this.xdataType == XValueDataType.Integer)
					{
						num = int.Parse(data);
						return (num - ((int) base.Engine.scatterMinNumber));
					}
					if (this.xdataType == XValueDataType.Float)
					{
						num = (int) Math.Min(float.Parse(data), 2.147484E+09f);
						return (num - base.Engine.scatterMinNumber);
					}
					if (this.xdataType != XValueDataType.DateTime)
					{
						return num;
					}
					DateTime time = DateTime.Parse(data);
					DateTime scatterMinDateTime = base.Engine.scatterMinDateTime;
					if (time == scatterMinDateTime)
					{
						return 1f;
					}
					TimeSpan span = time.Subtract(scatterMinDateTime);
					if (this.internalDateRenderMode == DateRenderModeOption.Years)
					{
						return (((float) (span.TotalDays / 365.25)) + 1f);
					}
					if (this.internalDateRenderMode == DateRenderModeOption.Months)
					{
						return (((float) (span.TotalDays / 30.4375)) + 1f);
					}
					if (this.internalDateRenderMode == DateRenderModeOption.Weeks)
					{
						return (((float) (span.TotalDays / 7)) + 1f);
					}
					if (this.internalDateRenderMode == DateRenderModeOption.Days)
					{
						return (((float) span.TotalDays) + 1f);
					}
					if (this.internalDateRenderMode == DateRenderModeOption.Hours)
					{
						return (((float) span.TotalHours) + 1f);
					}
					return (((float) span.TotalMinutes) + 1f);
				}
				catch (Exception exception)
				{
					throw new ApplicationException("Error while parsing the x value", exception);
				}
			}
			catch (ApplicationException)
			{
			}
			return num;
		}

		public override void Render(Graphics graphics, int width, int height)
		{
			ChartEngine engine = base.Engine;
			float scaleX = engine.scaleX;
			float scaleY = engine.scaleY;
			Pen pen = base.Line.GetPen(graphics);
			Point empty = Point.Empty;
			float xValueForData = 1f;
			float num4 = scaleX / 2f;
			Point[] points = new Point[base.Data.Count];
			int num5 = 1;
			bool flag = (base.shadow != null) && base.Shadow.Visible;
			Pen pen2 = null;
			Point[] pointArray2 = null;
			if (flag)
			{
				pointArray2 = new Point[base.Data.Count];
				pen2 = new Pen(base.Shadow.Color);
			}
			foreach (ChartPoint point3 in base.Data)
			{
				int y = (int) (point3.yvalue * scaleY);
				xValueForData = this.GetXValueForData(point3.xvalue);
				int x = (int) ((xValueForData * scaleX) - num4);
				Point point2 = new Point(x, y);
				if (base.showLineMarkers)
				{
					base.lineMarker.Render(graphics, x, y);
				}
				if (this.ScatterLines == ScatterLinesOption.Lines)
				{
					if (num5 > 1)
					{
						if (flag)
						{
							graphics.DrawLine(pen2, (int) (empty.X + base.shadow.OffsetX), (int) (empty.Y + base.shadow.OffsetY), (int) (point2.X + base.shadow.OffsetX), (int) (point2.Y + base.shadow.OffsetY));
						}
						graphics.DrawLine(pen, empty, point2);
					}
					empty = point2;
				}
				else if (this.ScatterLines == ScatterLinesOption.SmoothLines)
				{
					if (flag)
					{
						pointArray2[num5 - 1] = new Point(x + base.shadow.OffsetX, y + base.shadow.OffsetY);
					}
					points[num5 - 1] = new Point(x, y);
				}
				num5++;
				xValueForData += 1f;
			}
			if (this.scatterLines == ScatterLinesOption.SmoothLines)
			{
				if (flag)
				{
					graphics.DrawCurve(pen2, pointArray2);
				}
				graphics.DrawCurve(pen, points);
			}
			if (base.dataLabels.visible)
			{
				base.RenderDataLabels(graphics);
			}
		}

		// Properties
		[DefaultValue(0)]
		public DateRenderModeOption DateRenderMode
		{
			get
			{
				return this.dateRenderMode;
			}
			set
			{
				this.dateRenderMode = value;
			}
		}

		[DefaultValue(1)]
		public ScatterLinesOption ScatterLines
		{
			get
			{
				return this.scatterLines;
			}
			set
			{
				this.scatterLines = value;
			}
		}

		[DefaultValue(1)]
		public XValueDataType XDataType
		{
			get
			{
				return this.xdataType;
			}
			set
			{
				this.xdataType = value;
			}
		}

		// Nested Types
		public enum DateRenderModeOption
		{
			Automatic,
			Years,
			Months,
			Weeks,
			Days,
			Hours,
			Minutes
		}

		public enum ScatterLinesOption
		{
			NoLines,
			Lines,
			SmoothLines
		}

		public enum XValueDataType
		{
			Integer,
			Float,
			DateTime
		}
	}
}
